package teamproject.graphEditor.graphPainters;

import java.awt.Point;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import teamproject.graphEditor.Controller;
import teamproject.graphEditor.Node;
import teamproject.graphEditor.PDEEdge;
import edu.uci.ics.jung.graph.DirectedGraph;
import edu.uci.ics.jung.visualization.VisualizationViewer;

public class TreePainter implements GraphPainter {

	private Controller control;
	private VisualizationViewer<Node, PDEEdge> vv;

	private Map<Node, Integer> basePositions = new HashMap<Node, Integer>();
	private Set<Node> alreadyDone = new HashSet<Node>();

	public static int DEFAULT_DISTX = 50;
	public static int DEFAULT_DISTY = 50;

	private Point currentPoint = new Point();

	public TreePainter(Controller control) {
		this.control = control;

	}

	private void buildTree() {
		currentPoint = new Point(0, 20);
		Node root = null;

		for (Node node : control.getGraphEditor().getGraph().getVertices()) {
			if (control.getGraphEditor().getGraph().inDegree(node) == 0) {
				root = node;
				break;
			}
		}

		calculateDimensionX(root);
		currentPoint.x += basePositions.get(root) / 2 + DEFAULT_DISTX;
		buildTree(root, currentPoint.x);
	}

	private void buildTree(Node n, int x) {
		if (!alreadyDone.contains(n)) {
			alreadyDone.add(n);

			// go one level further down
			currentPoint.y += DEFAULT_DISTY;
			currentPoint.x = x;

			setCurrentPositionFor(n);

			int sizeXofCurrent = basePositions.get(n);

			int lastX = x - sizeXofCurrent / 2;

			int sizeXofChild;
			int startXofChild;

			for (Node child : control.getGraphEditor().getGraph()
					.getSuccessors(n)) {
				sizeXofChild = basePositions.get(child);
				startXofChild = lastX + sizeXofChild / 2;
				buildTree(child, startXofChild);
				lastX = lastX + sizeXofChild + DEFAULT_DISTX;
			}
			currentPoint.y -= DEFAULT_DISTY;
		}
	}

	private int calculateDimensionX(Node n) {
		int size = 0;
		int childrenNum = control.getGraphEditor().getGraph().getSuccessors(n)
				.size();

		if (childrenNum != 0) {
			for (Node child : control.getGraphEditor().getGraph()
					.getSuccessors(n)) {
				size += calculateDimensionX(child) + DEFAULT_DISTX;
			}
		}
		size = Math.max(0, size - DEFAULT_DISTX);
		basePositions.put(n, size);

		return size;
	}

	@Override
	public void paintGraph(DirectedGraph<Node, PDEEdge> g) {

		vv = this.control.getGraphEditor().getVisualizationViewer();
		vv.getGraphLayout().setGraph(g);
		buildTree();
		vv.repaint();
	}

	private void setCurrentPositionFor(Node n) {
		vv.getGraphLayout().setLocation(n, currentPoint);
	}
}
